
#include "GUI.h"
#include "Global.h"
#include "Functions.h"

CGUIWindow::CGUIWindow(GUI_PARAMS* params, GUI_COLORS* colors, GUI_SPRITES* sprites, bool _movable, LPCSTR _title){
	Init(params, colors, sprites);
	m_pFocusElement=NULL;
	m_Title=_title;
	m_bMovable = _movable;
	m_pGUIList = new LinkedList<CGUIBase>();
	m_pGUIDrawList = new LinkedList<CGUIBase>();
	m_pGUIit=NULL;
	m_pElement=NULL;
	m_Type=GUITYPE_WINDOW;
	m_numOfElements=0;
};
CGUIWindow::~CGUIWindow(){};

bool CGUIWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ){
	if(!GetEnabled())
		return false;

	m_pGUIit= m_pGUIList->first();
	while(m_pGUIit!=NULL){
		m_pElement = m_pGUIit->object;
		//If component in the window handles the msg, no need for others to try
		if(m_pElement!=NULL && m_pElement->WndProc( hWnd, uMsg, wParam, lParam)){
			return true;
		}
		m_pGUIit = m_pGUIit -> next;
	}
	switch(uMsg){
		// Keyboard messages
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
			return HandleKeyboard( uMsg, wParam, lParam );
		//Mouse Messages
		case WM_MOUSEMOVE:
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_MBUTTONDOWN:
        case WM_MBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
        case WM_XBUTTONDOWN:
        case WM_XBUTTONUP:
        case WM_LBUTTONDBLCLK:
        case WM_MBUTTONDBLCLK:
        case WM_RBUTTONDBLCLK:
        case WM_XBUTTONDBLCLK:
        case WM_MOUSEWHEEL:
			return HandleMouse( uMsg, wParam, lParam );
		default:
			return false;
	}
}
bool CGUIWindow::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) { 
	if(GetFocus() && wParam==m_Hotkey){
		OnHotkey();
		return true;
	}
	switch(uMsg){
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
			switch(wParam){
				case VK_TAB:
					FocusNext();
					return true;
				default:
					return false; 
			}
		default:
			return false;
	}
}
bool CGUIWindow::HandleMouse( UINT uMsg, WPARAM wParam, LPARAM lParam ) { 
	POINT MousePos;
	GetCursorPos(&MousePos);
	switch(uMsg){
		case WM_MOUSEMOVE:
			if(m_bButtonDown && m_bMovable){
				Move(V((float)(MousePos.x-m_mouseStart.x), (float)(MousePos.y-m_mouseStart.y)));
				m_mouseStart=MousePos;
				return true;
			}
			if(PtInBB(MousePos) && !m_bMouseOver && GetVisible()){
				OnMouseEnter();
				return true;
			}if(!PtInBB(MousePos) && m_bMouseOver){
				OnMouseLeave();
				return true;
			}

			break;
		case WM_LBUTTONDOWN:
			SetFocusElement(NULL);
			if(m_bMouseOver){
				if(!m_bButtonDown)
					if(GetFocus() || RequestFocus()){
						m_bButtonDown=true;
						m_mouseStart=MousePos;
					}
				return true;
				this;
			}
		case WM_LBUTTONUP:
			m_bButtonDown=false;
		default:
			if(m_bMouseOver)
				return true;
			return false; 
	}
	return false;
}

bool CGUIWindow::FocusNext(){
	if(m_pFocusElement==NULL)
		return false;

	bool nextFocus=false;
	m_pGUIit= m_pGUIList->first();
	while(m_pGUIit!=NULL){
		m_pElement = m_pGUIit->object;
		if(nextFocus && m_pElement){
			if(m_pElement->RequestFocus())
				return true;
			if(m_pElement==m_pFocusElement && !m_pElement->CanHaveFocus()){
				SetFocusElement(NULL);
				return true;
			}
		}

		if(m_pElement!=NULL && m_pElement->GetFocus()){
			nextFocus=true;
		}
		m_pGUIit = m_pGUIit -> next;
		if(nextFocus && m_pGUIit==NULL)
			m_pGUIit=m_pGUIList->first();
	}
	return false;
}
bool CGUIWindow::RequestFocus() {
	if(GetFocus())
		return true;
	if(m_pParent){
		if(CanHaveFocus()){
			return ((CGUIWindow*)m_pParent)->SetFocusElement(this);
		}
	}
	return false;
}
bool CGUIWindow::CanHaveFocus(){
	if((m_pParent && ((CGUIWindow*)m_pParent)->GetFocusElement() && ((CGUIWindow*)m_pParent)->GetFocusElement()->GetFocusLock()) || !GetEnabled() || (m_pFocusElement && m_pFocusElement->GetFocusLock()))
		return false; 

	return true;
}
bool CGUIWindow::SetFocusElement(CGUIBase* _element){
	if(m_pFocusElement!=NULL)
		m_pFocusElement->OnFocusOut();
	m_pFocusElement=_element;
	if(m_pFocusElement!=NULL){
		m_pFocusElement->OnFocusIn();
		float d=m_pFocusElement->getDepth();
		m_pGUIit= m_pGUIList->first();
		while(m_pGUIit!=NULL){
			m_pElement = m_pGUIit->object;
			if(m_pElement && m_pFocusElement->GetType()==GUITYPE_WINDOW && m_pElement->getDepth()>d)
				m_pElement->SetDepth(m_pElement->getDepth()-1);
			m_pGUIit = m_pGUIit -> next;
		}
		if(m_pFocusElement->GetType()==GUITYPE_WINDOW){
			m_pFocusElement->SetDepth(1);
			SortGUIList(m_pGUIList, m_pGUIDrawList);
		}
	}
	return true;
}
void CGUIWindow::OnFocusIn() { 
	m_bHasFocus = true; 
	SetVisible(true);
}
void CGUIWindow::OnFocusOut() { 
	m_bHasFocus = false; 
}
void CGUIWindow::OnMouseEnter() { 
	m_bMouseOver = true;
//	g_pCursor=m_pSprites->g_pCursor;
}
void CGUIWindow::OnMouseLeave() {
	m_bMouseOver = false; 
}
void CGUIWindow::OnHotkey() {}

void CGUIWindow::Add(CGUIBase* _GUI){
	if(!_GUI->GetParent())
		_GUI->SetParent(this);
	if(!_GUI->GetEventFunction())
		_GUI->SetEventFunction( OnGUIEvent );
	_GUI->SetDepth((float)m_numOfElements*-1);
	m_pGUIList->add(_GUI);
	m_pGUIDrawList->add(_GUI);
	SortGUIList(m_pGUIList, m_pGUIDrawList);
	++m_numOfElements;
}

void CGUIWindow::Step(){
	if(GetEnabled()){
		m_pGUIit= m_pGUIList->first();
		while(m_pGUIit!=NULL){
			m_pElement = m_pGUIit->object;
			if(m_pElement)
				m_pElement->Step();
			m_pGUIit = m_pGUIit -> next;
		}
	}
}
void CGUIWindow::Draw(){
	if(GetVisible()){
		UpdateBB();
		if(m_pSprites && m_pSprites->BG!=NULL)
			DrawSpriteExact(m_pSprites->BG, 0, m_drawpos);
		else
			DrawRectExact(m_drawpos, m_width, m_height, m_pColors->BG, m_border, m_pColors->Border);

		if(m_Title!="")
			DrawTextExact(g_pFontList->Arial20B, m_Title, V(m_drawpos.x+4, m_drawpos.y+4), m_pColors->Text);
		//if(GetFocus())
		//	DrawTextExact(g_pFontList->Arial20B, "Has Focus->", dx-128, dy+2, TextColor);

		//DrawTextExact(g_pFontList->Arial20B, "Depth: "+toStr(depth), dx, dy+50, TextColor);

		m_pGUIit= m_pGUIDrawList->first();
		while(m_pGUIit!=NULL){
			m_pElement = m_pGUIit->object;
			if(m_pElement)
				m_pElement->Draw();
			m_pGUIit = m_pGUIit -> next;
		}

		if(!GetEnabled())
			DrawRectExact(m_drawpos, m_width, m_height, D3DCOLOR_ARGB(128, 128, 128, 128));
	}
}